package clock.socoolby.com.clock.widget.animatorview.animator;

import android.graphics.Canvas;
import android.graphics.Paint;

import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry;

//引用自:https://blog.csdn.net/zeroblack/article/details/15351863
public class PhaserBallAnimator extends AbstractAnimator<PhaserBallAnimator.PhaserBall> {

    public static final String NAME="PhaserBall";

    public static final int V_MAX = 55;	//小球水平速度最大值
    public static final int V_MIN = 30;	//小球水平速度的最小值
    public static final int WOODEDGE = 140;	//木板的长度

    //根据你用的手机来设定
    public static final int UP_ZERO = 30;	//小球上升过程中，如果小于这个值，速度就为算为0
    public static final int DOWN_ZERO = 60;	//小球撞击地面后，如果速度小于该值就算为0

    public PhaserBallAnimator() {
        super(10);
    }

    public PhaserBallAnimator(int entryQuantity) {
        super(entryQuantity);
    }

    @Override
    public PhaserBall createNewEntry() {
        randomColorIfAble();
        return new PhaserBall(rand.nextInt(width),0,rand.nextInt(20),color);
    }

    public class PhaserBall implements I_AnimatorEntry {
        int startX = 0;
        int startY = 0;        //小球的初始坐标X,Y，小球的实时坐标应该等于初始坐标加位移
        int currentX;
        int currentY;        //实时坐标
        float startVX = 0f;
        float startVY = 0f;        //初始时水平和竖直方向的速度
        float currentVX = 0f;
        float currentVY = 0f;    //实时速度
        public int GROUND_LING=height;	//屏幕的底部，即屏幕最下方的Y坐标，表示小球落到底了
        int r;        //可移动物体的半径
        double timeX;
        double timeY;        //物体在X，Y上移动的时间，当物体从一个阶段进入到另一个阶段，此属性被重置
        //Bitmap bitmap = null;        //声明一个要使用的图片
        //BallThread bt = null;        //自己写的物理引擎，为一个线程，将根据物理公式对小球的位置坐标等属性修改
        boolean bFall = false;        //判断小球是否从木板上落下来了
        int color=0;
        float impactFactory = 0.25f;        //小球撞地后的速度衰减系数

        public PhaserBall(int x, int y, int r, int color) {
            init(x,y);
            this.r = r;
            this.color=color;
            ///this.bitmap = bitmap;
            /*
             * System.nanoTime是专门用来算间隔的(衡量时间段)。System.nanoTime()返回的是纳秒，nanoTime而返回的可能是任意时间，
             * 甚至可能是负数
             * System.currentTimeMillis()返回的毫秒，这个毫秒其实就是自1970年1月1日0时起的毫秒数，Date()其实就是相当于
             * Date(System.currentTimeMillis());因为Date类还有构造Date(long date)，用来计算long秒与1970年1月1日之间的毫秒差。
             */
            timeX = System.nanoTime();
            this.currentVX = V_MIN + (int) ((V_MAX - V_MIN) * Math.random());
            //上面这行是随机在水平向的最小和最大速度之间随便取个数作为水平初速度，正的，小球向右运动

        }

        private void init(int x,int y){
            this.startX = x;
            this.startY = y;
            this.currentX = x;
            this.currentY = y;        //构造函数初始化的时候，初始位置和实时位置相同
        }

        //Movable father;	//声明一个小球的实例
        //boolean flag = false;	//线程是否执行的标记
        //int sleepSpan = 40;	//休眠时间
        float g = 200;	//求落下的加速度
        double current;	//记录当前时间

        //run方法进行两项工作：（run方法又是整个这个类的核心）
        //（1）按照物理公式移动改变小球位置
        //（2）检测并处理小球达到最高点以及撞击地面的事件
        //而且，请各位注意，每个阶段一开始的时候，要把所有的时间的记录啊，X,Y的速度啊，X,Y位置啊之类的全更新
        public void run(){
                current = System.nanoTime();	//取得当前的时间
                //开始处理水平方向的运动
                //获取水平方向走过的时间，当前时间减掉小球初始化时候的时间，就是时间差，除以3个1000就得到s，nanotime得到的是ns
                double timeSpanX = (double)((current - timeX)/1000/1000/1000);
                currentX = (int)(startX + currentVX * timeSpanX);	//初始位置+速度*时间=当前位置，水平向是匀速的
                //下面处理竖直方向的运动
                if(bFall){	//bFall是判断小球有没有从木板上落下来，落下来了才有竖向速度
                    double timeSpanY = (double)((current - timeY)/1000/1000/1000);
                    currentY = (int)(startY + startVY * timeSpanY + timeSpanY * timeSpanY * g/2);	//s=vt+1/2at
                    currentVY = (float)(startVY + g * timeSpanY);	//求竖向当前速度，当前速度=v + at(高中物理)
                    //下面这个是判断小球是否达到最高点
                    if(startVY < 0 && Math.abs(currentVY) <= UP_ZERO){	//startVY<0证明小球是向上运动的
                        timeY = System.nanoTime();	//设置新的运动阶段竖直方向的开始时间
                        currentVY = 0;	//设置新的运动阶段竖直方向的实时速度，达到最高点是时，速度肯定为0
                        startVY = 0;	//设置新的运动阶段竖直方向的初始速度，达到最高点以后开始改变方向，起始速度为0
                        startY = currentY;	//设置新的运动阶段竖直方向的初始位置，这时刚刚要改变运动方向，所以初始位置=当前位置
                    }
                    //判断小球是否落地
                    if(currentY + r*2 >= GROUND_LING && currentVY > 0){
                        currentVX = currentVX * (1 - impactFactory);	//衰减水平方向的速度
                        currentVY = 0 - currentVY * (1 - impactFactory);	//衰减竖向的速度，并改变速度的方向（反弹）
                        if(Math.abs(currentVY) < DOWN_ZERO){	//如果衰减后的速度小于DOWN_ZERO，就停止线程的执行，Math.adb求绝对值
                            init(rand.nextInt(width),0);
                        }else{	//如果衰减后速度还够，就弹起
                            startX = currentX;	//弹起时水平方向的起始位置
                            timeX = System.nanoTime();	//记录弹起时的时间
                            startY = currentY;
                            timeY = System.nanoTime();
                            startVY = currentVY;
                        }
                    }
                }else if(currentX + r/2 >= WOODEDGE){	//当前位置加上小球半径的一半，大于这个值，小球就掉落了
                    //WOODEDGE是木板的长度
                    timeY = System.nanoTime();	//记录竖直方向上的开始运动时间
                    bFall = true;	//一定会先执行这个else，才执行上面这个if，即timeY会先有值。看判断条件
                }

        }

        @Override
        public void move(int maxWidth, int maxHight) {
              run();
              if(currentX>width)
                  init(rand.nextInt(width),0);
        }

        @Override
        public void onDraw(Canvas canvas, Paint mPaint) {
            mPaint.setColor(color);
            canvas.drawCircle(currentX,currentY,r,mPaint);
        }

        @Override
        public void setAnimatorEntryColor(int color) {
            this.color=color;
        }
    }
}
